import urllib, urllib2
import ssl
import json
from configs import ACC_ACCESS_LIMIT
import configs as CONFIG
from WeiboAPI import SearchAPI
import time

class RelationshipDownloader(object):
    def __init__(self):
        self.base_api = 'https://api.weibo.cn/2/cardlist?' \
                        'networktype=wifi&uicode=10000011&moduleID=708&featurecode=10000001&c=android' \
                        '&i=b02c74a&ua=OPPO-OPPO%20R9%20Plusm%20A__weibo__6.11.2__android__android5.1.1&wm=9847_0002' \
                        '&aid=01AqnUvzp73TXy3GLdDRCQXansQh0WdGR_fMeitNbMEiHh-8k.' \
                        '&uid=6032206936&v_f=2&v_p=39&from=106B295010' \
                        '&imsi=460030765213241&lang=zh_CN&lfid=1076032331621641_-_WEIBO_SECOND_PROFILE_WEIBO' \
                        '&skin=default&count=20&oldwm=9893_0044&sflag=1&need_head_cards=0'
        self.api = ''

    def group_api(self, account, seed, page, type):
        '''

        :param account:
        :param seed:
        :param page:
        :param type: ['followers','fans']
        :return:
        '''
        self.api = self.base_api

        s = '&s=' + account.s
        gsid = '&gsid=' + account.gsid
        page = '&page=%d' % (page,)

        fid = '&fid=231051_-_' + type + '_-_' + str(seed.uid)

        containerid = '&containerid=231051_-_' + type + '_-_' + str(seed.uid)

        self.api = self.api + s + gsid + fid + containerid + page

    def download_relationship(self, account, seed, page, type):
        '''

        :param account:
        :param seed:
        :param page:
        :param type: followers or fans
        :return:
        '''
        self.group_api(account, seed, page, type)

        context = ssl._create_unverified_context()
        while True:
            if account.count > ACC_ACCESS_LIMIT:
                return None

            try:
                print '%d access for account %s...' % (account.count + 1, account.username)
                relationships = urllib2.urlopen(self.api, context=context).read()
                account.count += 1
                return json.loads(relationships)
            except Exception as e:
                account.count += 1
                print e


class Downloader(object):
    def __init__(self):
        self.search_api = SearchAPI
        self.api = ''
        self._account = None

    def group_api(self, account, keyword, page):
        _keyword = keyword

        self.search_api['s'] = account.s
        self.search_api['gsid'] = account.gsid
        self.search_api['page'] = str(page)

        _keyword = keyword.encode('utf8')
        _keyword = urllib.quote(_keyword)

        self.search_api['containerid'] = '230926type%3D65%26q%3D' + _keyword
        self.search_api['lfid'] = '230926type%3D42%26q%3D' + _keyword
        self.search_api['fid'] = self.search_api['containerid']

        self.api = self.search_api['prefix']  # reset API
        for para in self.search_api:
            if para != 'prefix':
                self.api += para + '=' + self.search_api[para] + '&'
        self.api = self.api.strip('&')

        return self.api

    def download(self, account, keyword, page):
        self._account = account

        self.group_api(account, keyword, page)

        context = ssl._create_unverified_context()
        while True:
            print "Account %s access the server for %d times!" % (account.username, account.count)  # for debug
            if account.count > ACC_ACCESS_LIMIT:
                return None  # account runs out of access times
            try:
                data = urllib2.urlopen(self.api, context=context, timeout=CONFIG.HTTP_TIMEOUT).read()
                account.count += 1
                return json.loads(data)
            except Exception as e:
                account.count += 1
                self.handle_exceptions(e)

    def handle_exceptions(self, exception):
        print exception.message
        print '--------------------------------------------------------------------------------'
        code = exception.code
        if code == 414:
            print 'Sleeping for %d seconds...' % (CONFIG.REST_TIME_FOR_403,)
            time.sleep(CONFIG.REST_TIME_FOR_403)
            return 'OK'
        elif code == 403:
            self._account.count += CONFIG.ACC_ACCESS_LIMIT
            return '403: Account has been banned.'
        else:
            return 'Unknown Exception'

